home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
haeberli
/
libgutil
/
invmap.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
7KB
|
286 lines
/*
* Copyright 1992, 1993, 1994, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*/
/*
* invmap -
* Make and use inverse maps for dithering
*
* Paul Haeberli - 1992
*/
#include "math.h"
#include "invmap.h"
#include "lum.h"
#define OFFSET_R 3
#define OFFSET_G 2
#define OFFSET_B 1
#define OFFSET_A 0
static int ethresh;
ditthresh(t)
int t;
{
ethresh = t;
}
static int getindex(m,or,og,ob)
invmap *m;
int or,og,ob;
{
int i, r, g, b;
int dist, goodi, bestd;
int dr, dg, db;
unsigned char *rm, *gm, *bm;
goodi = -1;
bestd = 200000;
if(m->bwmaps) {
rm = m->rmap;
for(i=0; i<m->maplen; i++) {
dist = or-(int)rm[i];
if(dist<0)
dist = -dist;
if(dist<bestd) {
goodi = i;
bestd = dist;
}
}
} else {
rm = m->rmap;
gm = m->gmap;
bm = m->bmap;
for(i=0; i<m->maplen; i++) {
dr = or-(int)rm[i];
dg = og-(int)gm[i];
db = ob-(int)bm[i];
dist = dr*dr+dg*dg+db*db;
if(dist<bestd) {
goodi = i;
bestd = dist;
}
}
}
return goodi;
}
invmap *makeinvmap(rmap,gmap,bmap,maplen,tlevels)
unsigned char *rmap, *gmap, *bmap;
int maplen;
int tlevels;
{
invmap *m;
unsigned char *pptr;
int r, g, b, i;
int ir, ig, ib;
float div;
m = (invmap *)malloc(sizeof(invmap));
m->rmap = (unsigned char *)malloc(maplen*sizeof(char));
m->gmap = (unsigned char *)malloc(maplen*sizeof(char));
m->bmap = (unsigned char *)malloc(maplen*sizeof(char));
m->maplen = maplen;
bcopy(rmap,m->rmap,maplen);
bcopy(gmap,m->gmap,maplen);
bcopy(bmap,m->bmap,maplen);
m->bwmaps = 1;
for(i=0; i<maplen; i++) {
if(rmap[i] != gmap[i] || gmap[i] != bmap[i]) {
m->bwmaps = 0;
break;
}
}
if(m->bwmaps) {
m->tlevels = 256;
m->table = (unsigned char *)malloc(256*sizeof(char));
pptr = m->table;
for(i=0; i<256; i++)
*pptr++ = getindex(m,i,i,i);
} else {
m->tlevels = tlevels;
m->table = (unsigned char *)malloc(tlevels*tlevels*tlevels*sizeof(char));
div = tlevels-1.0;
pptr = m->table;
for(b=0; b<tlevels; b++) {
ib = 255.0*b/div;
for(g=0; g<tlevels; g++) {
ig = 255.0*g/div;
for(r=0; r<tlevels; r++) {
ir = 255.0*r/div;
*pptr++ = getindex(m,ir,ig,ib);
}
}
}
}
return m;
}
freeinvmap(map)
invmap *map;
{
free(map->table);
free(map->rmap);
free(map->gmap);
free(map->bmap);
free(map);
}
static int buflen;
static short *rerr;
static short *gerr;
static short *berr;
int ditarray(map,lbuf,obuf,xsize,ysize,dodither)
invmap *map;
unsigned long *lbuf;
unsigned char *obuf;
int xsize, ysize, dodither;
{
int ir, ig, ib, y;
int i, l1, l2, sc, maxi;
unsigned char *base, *ipix;
int rwant, error;
int gwant;
int bwant;
int rerror, rnext;
int gerror, gnext;
int berror, bnext;
int index, n, nmalloc;
int outside;
unsigned char *rmap, *gmap, *bmap;
base = map->table;
rmap = map->rmap;
gmap = map->gmap;
bmap = map->bmap;
ipix = (unsigned char *)lbuf;
l1 = map->tlevels;
l2 = l1*l1;
sc = l1;
maxi = l1-1;
if(dodither) {
nmalloc = xsize+1;
if(buflen<nmalloc) {
if(rerr) {
rerr = (short *)realloc(rerr,nmalloc*sizeof(short));
gerr = (short *)realloc(gerr,nmalloc*sizeof(short));
berr = (short *)realloc(berr,nmalloc*sizeof(short));
} else {
rerr = (short *)malloc(nmalloc*sizeof(short));
gerr = (short *)malloc(nmalloc*sizeof(short));
berr = (short *)malloc(nmalloc*sizeof(short));
}
buflen = nmalloc;
}
bzero(rerr,nmalloc*sizeof(short));
if(map->bwmaps) {
for(y=0; y<ysize; y++) {
rerror = 0;
rnext = rerr[0] = 0;
for(i=0; i<xsize; i++) {
rwant = ILUM(ipix[OFFSET_R],ipix[OFFSET_G],ipix[OFFSET_B])
+ rerror + rnext;
ipix += 4;
if(rwant>255) rwant = 255;
if(rwant<0) rwant = 0;
index = *obuf++ = base[rwant];
error = rwant-rmap[index];
if(error<ethresh && error>-ethresh)
error = 0;
rerror = (3*error)/8;
rerr[i] += rerror;
rnext = rerr[i+1];
rerr[i+1] = error-2*rerror;
}
}
} else {
bzero(gerr,nmalloc*sizeof(short));
bzero(berr,nmalloc*sizeof(short));
for(y=0; y<ysize; y++) {
rerror = 0;
rnext = rerr[0] = 0;
gerror = 0;
gnext = gerr[0] = 0;
berror = 0;
bnext = berr[0] = 0;
for(i=0; i<xsize; i++) {
rwant = (int)ipix[OFFSET_R] + rerror + rnext;
gwant = (int)ipix[OFFSET_G] + gerror + gnext;
bwant = (int)ipix[OFFSET_B] + berror + bnext;
ipix += 4;
if(rwant>255) rwant = 255;
if(rwant<0) rwant = 0;
if(gwant>255) gwant = 255;
if(gwant<0) gwant = 0;
if(bwant>255) bwant = 255;
if(bwant<0) bwant = 0;
ir = (rwant*sc)>>8;
ig = (gwant*sc)>>8;
ib = (bwant*sc)>>8;
index = *obuf++ = base[(ir+ig*l1+ib*l2)];
error = rwant-rmap[index];
if(error<ethresh && error>-ethresh)
error = 0;
rerror = (3*error)/8;
rerr[i] += rerror;
rnext = rerr[i+1];
rerr[i+1] = error-2*rerror;
error = gwant-gmap[index];
if(error<ethresh && error>-ethresh)
error = 0;
gerror = (3*error)/8;
gerr[i] += gerror;
gnext = gerr[i+1];
gerr[i+1] = error-2*gerror;
error = bwant-bmap[index];
if(error<ethresh && error>-ethresh)
error = 0;
gerror = (3*error)/8;
berror = (3*error)/8;
berr[i] += berror;
bnext = berr[i+1];
berr[i+1] = error-2*berror;
}
}
}
} else {
n = xsize*ysize;
if(map->bwmaps) {
while(n--) {
*obuf++ = base[ILUM(ipix[OFFSET_R],
ipix[OFFSET_G],ipix[OFFSET_B])];
ipix += 4;
}
} else {
while(n--) {
ir = (ipix[OFFSET_R]*sc)/256;
ig = (ipix[OFFSET_G]*sc)/256;
ib = (ipix[OFFSET_B]*sc)/256;
*obuf++ = base[(ir+ig*l1+ib*l2)];
ipix += 4;
}
}
}
}